package com.xunlai.infra.permission.common.util;

import lombok.extern.slf4j.Slf4j;
import org.bouncycastle.crypto.digests.SM3Digest;
import org.bouncycastle.crypto.macs.HMac;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.pqc.math.linearalgebra.ByteUtils;

import java.io.UnsupportedEncodingException;
import java.security.Security;
import java.util.Arrays;

/**
 * @author yanguoliang
 * @date 2021/4/25 21:03
 */
@Slf4j
public class SM3Utils {

    private static final String ENCODING = "ISO-8859-1";

    static {
        Security.addProvider(new BouncyCastleProvider());
    }

    /**
     * sm3 加密
     * @param paramStr 待加密字符串
     *
     * @return 返回加密后，固定长度=32的16进制字符串
     */
    public static String encrypt(String paramStr){
        String resultHexString = "";
        try {
            byte[] srcData = paramStr.getBytes(ENCODING);
            byte[] resultHash = hash(srcData);
            resultHexString = ByteUtils.toHexString(resultHash);
        }catch (UnsupportedEncodingException e){
            log.error(e.getMessage(),e);
        }
        return resultHexString;
    }


    private static byte[] hash(byte[] srcData){
        SM3Digest digest = new SM3Digest();
        digest.update(srcData,0,srcData.length);
        byte[] hash = new byte[digest.getDigestSize()];
        digest.doFinal(hash,0);
        return hash;
    }

    /**
     * sm3 加密， 自定义key
     * @param key key
     * @param srcData 待加密字符串
     * @return
     */
    public static byte[] hmac(byte[] key, byte[] srcData){
        KeyParameter keyParameter = new KeyParameter(key);
        SM3Digest digest = new SM3Digest();
        HMac hMac = new HMac(digest);
        hMac.init(keyParameter);
        hMac.update(srcData,0,srcData.length);
        byte[] result = new byte[hMac.getMacSize()];
        hMac.doFinal(result,0);
        return result;
    }


    /**
     *  判断原数据与加密数据是否一致，
     * @param srcStr 原字符串
     * @param sm3HexString 16进制字符串
     * @return
     */
    public static boolean verify(String srcStr,String sm3HexString){
        try {
            byte[] srcData = srcStr.getBytes(ENCODING);
            byte[] sm3Hash = ByteUtils.fromHexString(sm3HexString);
            byte[] newHash = hash(srcData);
            if(Arrays.equals(newHash,sm3Hash)){
                return true;
            }
        }catch (UnsupportedEncodingException e){
            log.error(e.getMessage(),e);
        }
        return false;
    }


    public static String bytesToHexString(byte[] srcData) {
        return ByteUtils.toHexString(srcData);
    }

    public static byte[] hexStringToBytes(String sm3HexString) {
        return ByteUtils.fromHexString(sm3HexString);
    }
}
